<?php
namespace app\common\lib\module_config\tagsconfig;

use app\common\lib\model_operate\QueryDevice;
use app\common\lib\model_operate\Tools;
use app\common\lib\module_config\TagsConfig;
use app\common\lib\module_config\tagsconfig\Search;
use think\Db;
use app\common\lib\file_operate\CsvOperate;

/**
 * table标签类
 */
class Table extends TagsConfig
{

    private $where; // 根据search 参数规则生成的查询条件

    private $displayFields; //显示字段 [ 'id'=>'ID' , 'name' => '会员名' ];

    private $base; //主表信息

    private $relevance; //关联信息

    public function __construct($trace, $tags)
    {
        parent::__construct($trace, $tags);

        //设置主表信息
        $this->setBase();
        //设置显示字段信息
        $this->setDisplayFields();
        //解析配置信息
        $this->analyticConfig();
    }

    /**
     * 设置主表信息
     */
    private function setBase()
    {
       if(empty($this->config['database'])){
            //主表名
            $this->base['tableName'] = Tools::tableNameFormat($this->trace->getApp(), 1);
        }else{
            //主表名
            $this->base['tableName'] = Tools::tableNameFormat($this->config['database'], 1);
        }        
        //获取主表字段
        $this->base['tableInfo']     = DB::getTableInfo($this->base['tableName']);
        $this->base['displayFields'] = [];
    }

    /**
     * 获取主表信息
     */
    public function getBase()
    {
        return $this->base;
    }

    /**
     * 设置动态参数
     * @param $searchObj Search标签类对象
     */
    public function setParam($search = null)
    {   
        if ($search instanceof Search) {
            $rule   = $search->getRule();
            $params = $search->getParam();

            //解析规则,获取搜索where
            $where = [];
            if (!empty($rule)) {
                foreach ($rule as $index => $rule) {
                    $where[] = $this->replaceRule($params, $rule, $params[$index]);
                }
                if (!empty($where)) {
                    $this->where = implode(' AND ', array_filter($where));
                }
            }
        } else {
            throw new \Exception("Table标签依赖Search对象");
        }
    }

    /**
     * 替换规则
     */
    private function replaceRule($params, $rule, $selfValue)
    {
        if (empty($selfValue)) {
            return '';
        }

        $search  = ['$val'];
        $replace = [$selfValue];

        if (false !== strpos($rule, '$val')) {
            if (false !== strpos($rule, '%$val%')) {
                $rule = str_replace('%$val%', "'" . '%$val%' . "'", $rule);
            } else {
                $rule = str_replace('$val', "'" . '$val' . "'", $rule);
            }
        }

        $isOk = true;
        foreach ($params as $key => $value) {
            $tmpKey = '$' . $key;
            //如果在rule 匹配到参数名 并且 值为空,则规则置空
            if (false !== strpos($rule, $tmpKey) && empty($value)) {
                $isOk = false;
                break;
            }

            if (false !== strpos($rule, '%' . $tmpKey . '%')) {
                $tmpKey = '%' . $tmpKey . '%';
                $value  = "%" . $value . "%";
            }

            if (in_array($key, $this->base['tableInfo']['fields'])) {
                $tmpKey = $key;
                $value  = $this->base['tableName'] . '.' . $key;
            }
            $search[]  = $tmpKey;
            $replace[] = $value;
        }

        if (false == $isOk) {
            return '';
        }

        $tagKeys  = array_keys($this->getTagMap());
        $tagValue = array_values($this->getTagMap());

        $search  = array_merge($search, $tagKeys);
        $replace = array_merge($replace, $tagValue);
        $rule    = str_replace($search, $replace, $rule);
        $pos = strpos($rule, '$');
        return (false !== $pos) ? '' : $rule;
    }

    /**
     * 获取搜索参数的条件
     */
    public function getWhere()
    {
        return $this->where;
    }

    /**
     * 配置解析
     */
    private function analyticConfig()
    {
        $reFieldsTmp = [];

        //是否设置了关联
        $r = array_filter($this->config['fields'],function($t) {return $t['is_relevance'] == 1;});
        //解析关联信息
        if (!empty($r) && isset($this->config['relevance']) && !empty($this->config['relevance'])) {
            $relevance                          = $this->config['relevance'];
            $this->relevance['relevanceTables'] = [];

            //关联类型
            if (!isset($this->config['relevanceType'])) {
                $this->relevance['relevanceType']['queryType'] = 'Single'; //默认设置未单表查询
            } else {
                $this->relevance['relevanceType']['queryType'] = $this->config['relevanceType']['queryType']; //
            }

            //关联信息
            foreach ($relevance as $key => $items) {
                $items = json_decode($items, true);

                //关联信息临时容器
                $relevanceTmp = [];
                if (empty($items) || !is_array($items) || count($items) != 5) {
                    continue;
                }
                list($mainTable, $relevanceTable, $condition, $way, $displayFields) = $items;
                $relevanceTmp[0]                                                    = $relevanceTable;
                $relevanceTmp[1]                                                    = $condition;
                $relevanceTmp[2]                                                    = $way;
                //追加关联信息中要显示的字段
                $displayStr = '';

                if (!empty($displayFields) && is_array($displayFields)) {
                    foreach ($displayFields as $fieldName => $aliasName) {
                        $name = empty($aliasName) ? $fieldName : $aliasName;

                        if (!isset($this->displayFields[$name])) {
                            continue;
                        }

                        //只要fields中存在该字段就显示,不管是否设置is_show=1
                        $title                      = isset($this->fields[$name]['title']) && !empty($this->fields[$name]['title']) ? $this->fields[$name]['title'] : $name;

                        $this->displayFields[$name] = $title;
                        $reFieldsTmp[]              = $name;
                        //关联查询时设置的显示字段
                        $relevanceTmp[3][$name] = empty($aliasName) ? $relevanceTable . '.' . $fieldName : $relevanceTable . '.' . $fieldName . ' as ' . $aliasName;
                    }
                }

                if (!empty($relevanceTmp) && count($relevanceTmp) == 4) {
                    $this->relevance['relevanceTables'][] = $relevanceTmp;
                }
            }

        }

        //过滤要显示的字段, 将即不再基础表,也没有关联表的字段拿掉
        if (!empty($this->displayFields)) {
            foreach ($this->displayFields as $fieldName => $aliasName) {
                if (!in_array($fieldName, $this->base['displayFields']) && !in_array($fieldName, $reFieldsTmp)) {
                    echo '过滤:' . $fieldName;
                    unset($this->displayFields[$fieldName]);
                }
            }
        }

    }

    /**
     *设置要显示的字段信息
     */
    private function setDisplayFields()
    {
        if (!empty($this->fields)) {
            foreach ($this->fields as $key => $value) {
                if(!empty($value['permission']) && $value['permission'] == '1'){
                    //检查权限
                    $check = ( new \plugins\store\Common )->getAllowAccess();
                    if($check === true){
                        
                    }else{
                        continue;
                    }
                }                 
                if ($value['is_show'] == 1) {
                    $index                       = empty($value['alias']) ? $key : $value['alias'];
                    $this->displayFields[$index] = empty($value['title']) ? $index : $value['title'];
                    //主表显示字段
                    if (in_array($key, $this->base['tableInfo']['fields'])) {
                        $this->base['displayFields'][$key] = $index;
                    }
                }
            }
        }
    }

    /**
     * 获取要显示的字段信息
     */
    public function getDisplayFields()
    {
        return $this->displayFields;
    }

    /**
     * 获取关联信息
     */
    public function getRelevance()
    {
        return $this->relevance;
    }

    /**
     * 执行查询
     */
    public function query()
    {
        $type = (isset($this->relevance['relevanceType']['queryType']) && !empty($this->relevance['relevanceType']['queryType'])) ? $this->relevance['relevanceType']['queryType'] : 'Single';
        // dump($this->getWhere());
        return QueryDevice::createQuery($this, $type);
    }

/*****************************/

    public function createQuery()
    {
        return '子类 Table 实现的获取数据方法';
    }

    //生成html代码的方法
    public function createHtml($value = null)
    {
        $html = '';
        if (empty($this->fields)) {
            return $html;
        }
        foreach ($this->fields as $k => $v) {
            if ($v['is_show'] == '2') {
                continue;
            }
            if(!empty($v['permission']) && $v['permission'] == '1'){
                //检查权限
                $check = ( new \plugins\store\Common )->getAllowAccess();
                if($check === true){
                }else{
                    continue;
                }
            }
            $html .= '<td style="max-width:200px;">';
            if (!empty($value[$k])) {
                //原参数输出
                if ($v['show_type'] == '1') {
                    if ($v['rule'] == 'image') {
                        $html .= "<img src='__ROOT__" . $value[$k] . "'>";
                    } else if ($v['rule'] == 'date') {
                        $html .= date('Y-m-d H:i:s', $value[$k]);
                    } else {
                        $html .= $value[$k];
                    }
                    //参数转换,固定内容
                } else if ($v['show_type'] == '2') {
                    //遍历转换设置
                    $option = json_decode($v['option'], true);

                    $option_keys = array_keys($option);
                    if (in_array($value[$k],$option_keys)) {
                        $html .= $option[$value[$k]];
                    } else {
                        $html .= $value[$k];
                    }
                    //查表替换
                } else if ($v['show_type'] == '3') {
                    $content = $this->selectGetTableData($v['option'], $value);
                    $html .= $content;
                }
            }
            $html .= '</td>';
        }
        return $html;
    }

    //表格头
    public function getHeader()
    {
        $html = '';
        if (empty($this->displayFields)) {
            return $html;
        }
        foreach ($this->displayFields as $key => $value) {
            /*if($value['is_show'] == '2'){
            continue;
            }*/
            $html .= '<th style="text-align:center;"><b>';
            $html .= $value; //$value['title'];
            $html .= '</b></th>';
        }
        return $html;
    }

    public function getConfig()
    {
        return $this->config;
    }

    /**
     * 查表显示数据
     */
    private function selectGetTableData($option, $content = null)
    {
        $da     = '';
        $option = json_decode($option, true);
        //要替换的字段
        $key1 = key($option['replace']);
        //替换字段
        $key2 = $option['replace'][$key1];
        //传入的参数
        $str = $content[$key1];
        if (!empty($option) && count($option) == 3) {
            // list( $table , $fields , $items ) = $option;
            //获得数据表
            $table = Tools::tableNameFormat($option['cmf']);
            //搜索结果
            $tb = Db::name($table)->field($option['field'])->select()->toArray();
            //遍历结果
            foreach ($tb as $key => $value) {
                if ($value[$key1] == $str) {
                    return $value[$key2];
                }
            }
        }
        return $da;
    }

    //导出
    public function export( $list , $name = null )
    {
    	$file = new CsvOperate;
    	//列表名
    	if($name == null ){
    		$name = time();
    	}
    	$file->fileName = $name.'.csv';
        
    	//列表头
    	$head = $this->displayFields;

    	//列表内容
    	$body = [];
    	foreach ($list as $key => $value) {
	        if (empty($this->fields)) {
	            return false;
	        }
	        foreach ($this->fields as $k => $v) {
	            if ($v['is_show'] == '2') {
	                continue;
	            }
	            if(!empty($v['permission']) && $v['permission'] == '1'){
	                //检查权限
	                $check = ( new \plugins\store\Common )->getAllowAccess();
	                if($check === true){
	                }else{
	                    continue;
	                }
	            }
	            if (!empty($value[$k])) {
	                //原参数输出
	                if ($v['show_type'] == '1') {
	                    if ($v['rule'] == 'image') {
	                    	$body[$key][$k] = $value[$k];
	                    } else if ($v['rule'] == 'date') {
	                        $body[$key][$k] = date('Y-m-d H:i:s', $value[$k]);
	                    } else {
	                        $body[$key][$k] = $value[$k];
	                    }
	                    //参数转换,固定内容
	                } else if ($v['show_type'] == '2') {
	                    //遍历转换设置
	                    $option = json_decode($v['option'], true);

	                    $option_keys = array_keys($option);
	                    if (in_array($value[$k],$option_keys)) {
	                        $body[$key][$k] = $option[$value[$k]];
	                    } else {
	                        $body[$key][$k] = $value[$k];
	                    }

	                    //查表替换
	                } else if ($v['show_type'] == '3') {
	                    $content = $this->selectGetTableData($v['option'], $value);
	                    $body[$key][$k] = $content;
	                }
	            } else {
	                $body[$key][$k] = '';
	            }
	        }
    	}
		$file->setFieldsInfo($head);
		$file->setSourceData($body);
		$return = $file->exportCsv();    	
    }

}
